package team119;

import battlecode.common.Clock;
import battlecode.common.Direction;
import battlecode.common.GameActionException;
import battlecode.common.GameConstants;
import battlecode.common.MapLocation;
import battlecode.common.RobotController;
import battlecode.common.Upgrade;

import java.util.Comparator;
import java.util.PriorityQueue;

public class BOTHeadquarters implements BOT 
{
	Boolean OUTPUT_DEBUG=true;
	PriorityQueue<MapLocation> enRouteEncampments;
	PriorityQueue<MapLocation> notEnRouteEncampments;
	int currentRoundSet = 0;
	int RoundSetSize = 600;
	boolean hasAlertedNuke = false;
	int lowPowerBeginRound = 0;
	boolean researchingDefusion = false;
	
	public void RunBot(RobotController rc) throws GameActionException
	{
		FillPriorityQueues(rc);
				
		while (true) {
			
			try {
				while (rc.isActive()) 
				{
					int RoundNum = Clock.getRoundNum();
					rc.setTeamMemory(0, RoundNum);
					UpdateBroadcastPoint(RoundNum, rc);
					if (rc.getTeamPower() < 25) {
						
						if (lowPowerBeginRound <= 0) {
							lowPowerBeginRound = RoundNum;
						} else {
							if (RoundNum - lowPowerBeginRound > 10){
								int atkRounds = rc.readBroadcast(2550 % GameConstants.BROADCAST_MAX_CHANNELS);
								rc.broadcast(2550 % GameConstants.BROADCAST_MAX_CHANNELS, 1);
							}
						}
					} else {
						rc.broadcast(2550 % GameConstants.BROADCAST_MAX_CHANNELS, 0);
					}
					
					if ((researchingDefusion && !rc.hasUpgrade(Upgrade.DEFUSION)) || RoundNum >= (GameConstants.HQ_SPAWN_DELAY*8) && RoundNum < (GameConstants.HQ_SPAWN_DELAY*8)+GameConstants.HQ_SPAWN_DELAY-1) {
						researchingDefusion = true;
						rc.researchUpgrade(Upgrade.DEFUSION);
					}
					
					// Spawn a soldier
					boolean shouldNuke = false;
					if (shouldNuke || (shouldNuke = GameConstants.ROUND_MAX_LIMIT - (Upgrade.NUKE.numRounds+20) < Clock.getRoundNum())) {
						while (true) {
							rc.researchUpgrade(Upgrade.NUKE);
							rc.yield();
						}
					}
					
					Direction dir = rc.getLocation().directionTo(rc.senseEnemyHQLocation());
					while(rc.senseMine(rc.getLocation().add(dir))!=null && rc.senseMine(rc.getLocation().add(dir))!=rc.getTeam() || !rc.canMove(dir))
							dir = dir.rotateLeft();
					if (rc.canMove(dir))
					{
						if(rc.getTeamPower()>GameConstants.UNIT_POWER_UPKEEP * 10)//Make sure there is enough power to support this spawn
							rc.spawn(dir);
						else
						{
							ResearchNextUpgrade(rc);
						}
					}
		
				}
				while (!rc.isActive()) {
					rc.setTeamMemory(0, Clock.getRoundNum());
					UpdateBroadcastPoint(Clock.getRoundNum(), rc);
					rc.yield();
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	
	private void FillPriorityQueues(RobotController rc) {
		MapLocation enemyHQ = rc.senseEnemyHQLocation();
		Comparator<MapLocation> comp = new MapLocationDistanceToEnemyHQComparator(enemyHQ);
		enRouteEncampments = new PriorityQueue<MapLocation>(10, comp);
		notEnRouteEncampments = new PriorityQueue<MapLocation>(10, comp);
				
		MapLocation[] all = rc.senseAllEncampmentSquares();
		
		for (int i = 0; i < all.length; i++) {
			if (all[i].distanceSquaredTo(enemyHQ) <= rc.getLocation().distanceSquaredTo(enemyHQ)) {
				enRouteEncampments.add(all[i]);
			} else {
				notEnRouteEncampments.add(all[i]);
			}
		}
		
	}

	private void UpdateBroadcastPoint(int roundNum, RobotController rc) {
		MapLocation ml = null;
		
		try {
			if (!hasAlertedNuke && rc.senseEnemyNukeHalfDone()) {
				hasAlertedNuke = true;
				rc.broadcast(2540 % GameConstants.BROADCAST_MAX_CHANNELS, rc.getLocation().x);
				rc.yield();
				rc.broadcast(2541 % GameConstants.BROADCAST_MAX_CHANNELS, rc.getLocation().y);
				return;
			}
		} catch (GameActionException e) {
			e.printStackTrace();
		}
		
		if (roundNum / RoundSetSize > currentRoundSet && !hasAlertedNuke) {
			currentRoundSet++;
			
			if (enRouteEncampments.size() > 0) {
				ml = enRouteEncampments.poll();
			} else if (notEnRouteEncampments.size() > 0) {
				ml = notEnRouteEncampments.poll();
			} else {
				ml = rc.senseEnemyHQLocation();
			}
			
			try {
				rc.broadcast(2540 % GameConstants.BROADCAST_MAX_CHANNELS, ml.x);
				rc.yield();
				rc.broadcast(2541 % GameConstants.BROADCAST_MAX_CHANNELS, ml.y);
			} catch (GameActionException e) {
				e.printStackTrace();
			}
		}
		
		
	}
	
	private void ResearchNextUpgrade(RobotController rc) throws GameActionException
	{
		Upgrade[] upgradeOrder={Upgrade.FUSION,Upgrade.DEFUSION,Upgrade.NUKE};
		for(Upgrade nextUpgrade :upgradeOrder)
		{
			if(!rc.hasUpgrade(nextUpgrade))
			{
				if(OUTPUT_DEBUG)System.out.println("Researching: "+nextUpgrade);
				rc.researchUpgrade(nextUpgrade);
				return;
			}
		}
		
	}
}
